import requests
import tkinter as tk
from tkinter import ttk, messagebox
from PIL import Image, ImageTk
import pyautogui
import io
import base64
import socket
import urllib.request

API_KEY = "YLOtSqjT6U6rZOmCUk466hAB"
SECRET_KEY = "ukICHsUhKDyoZ34neD06k4XwISKnV5AB"

class VehicleLicenseApp:
    def __init__(self, root):
        self.root = root
        self.root.title("智能行驶证识别")
        
        # 设置窗口大小和居中
        window_width = 1000
        window_height = 700
        screen_width = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        center_x = int(screen_width/2 - window_width/2)
        center_y = int(screen_height/2 - window_height/2)
        self.root.geometry(f'{window_width}x{window_height}+{center_x}+{center_y}')
        
        # 截图相关变量
        self.screenshot = None
        self.screenshot_tk = None
        self.start_x = None
        self.start_y = None
        self.rect = None
        self.capture_window = None
        
        # 存储识别结果
        self.result_data = []
        self.result_labels = []  # 存储所有结果标签
        
        # 网络状态变量
        self.network_status = tk.StringVar()
        self.network_status.set("状态：检测中...")
        
        # 创建界面
        self.create_widgets()
        
        # 初始网络状态检测
        self.update_network_status()
    
    def create_widgets(self):
        # 主框架
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 顶部按钮框架
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=10)
        
        # 截图按钮
        self.capture_btn = ttk.Button(
            button_frame, 
            text="截图识别", 
            command=self.start_capture
        )
        self.capture_btn.pack(side=tk.LEFT, padx=5)
        
        # 识别按钮
        self.recognize_btn = ttk.Button(
            button_frame, 
            text="识别行驶证", 
            command=self.recognize_license,
            state=tk.DISABLED
        )
        self.recognize_btn.pack(side=tk.LEFT, padx=5)
        
        # 清空按钮
        self.clear_btn = ttk.Button(
            button_frame, 
            text="清空", 
            command=self.clear_all
        )
        self.clear_btn.pack(side=tk.LEFT, padx=5)
        
        # 网络状态标签
        self.status_label = ttk.Label(
            button_frame,
            textvariable=self.network_status,
            font=('Arial', 10)
        )
        self.status_label.pack(side=tk.RIGHT, padx=10)
        
        # 内容框架
        content_frame = ttk.Frame(main_frame)
        content_frame.pack(fill=tk.BOTH, expand=True)
        
        # 图片显示区域 - 固定宽度
        self.image_frame = ttk.LabelFrame(content_frame, text="截图预览", width=500)
        self.image_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=False, padx=5, pady=5)
        self.image_frame.pack_propagate(False)  # 固定宽度
        
        self.image_label = ttk.Label(self.image_frame)
        self.image_label.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 识别结果区域 - 固定宽度
        self.result_frame = ttk.LabelFrame(content_frame, text="识别结果", width=450)
        self.result_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=False, padx=5, pady=5)
        self.result_frame.pack_propagate(False)  # 固定宽度
        
        # 使用Canvas和Frame实现可滚动的结果列表
        self.canvas = tk.Canvas(self.result_frame, borderwidth=0)
        self.scrollbar = ttk.Scrollbar(self.result_frame, orient="vertical", command=self.canvas.yview)
        self.scrollable_frame = ttk.Frame(self.canvas)
        
        self.scrollable_frame.bind(
            "<Configure>",
            lambda e: self.canvas.configure(
                scrollregion=self.canvas.bbox("all")
            )
        )
        
        self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
        self.canvas.configure(yscrollcommand=self.scrollbar.set)
        
        self.canvas.pack(side="left", fill="both", expand=True)
        self.scrollbar.pack(side="right", fill="y")
        
        # 底部信息栏
        footer_frame = ttk.Frame(main_frame)
        footer_frame.pack(fill=tk.X, pady=5)
        
        footer_label = ttk.Label(
            footer_frame, 
            text="智能行驶证识别工具",
            foreground="blue",
            font=('Arial', 10)
        )
        footer_label.pack()
    
    def check_internet(self):
        """检查网络连接状态"""
        try:
            urllib.request.urlopen('http://www.baidu.com', timeout=1)
            return True
        except (urllib.request.URLError, socket.timeout):
            return False
    
    def update_network_status(self):
        """更新网络状态显示"""
        if self.check_internet():
            self.network_status.set("状态：联 网")
            self.status_label.config(foreground="green")
        else:
            self.network_status.set("状态：离 线")
            self.status_label.config(foreground="red")
        
        # 每5秒检查一次网络状态
        self.root.after(5000, self.update_network_status)
    
    def start_capture(self):
        """开始截图流程"""
        self.root.withdraw()  # 隐藏主窗口
        
        # 创建全屏透明窗口用于截图
        self.capture_window = tk.Toplevel()
        self.capture_window.attributes('-fullscreen', True)
        self.capture_window.attributes('-alpha', 0.3)
        self.capture_window.attributes('-topmost', True)
        
        # 获取屏幕尺寸
        screen_width = self.capture_window.winfo_screenwidth()
        screen_height = self.capture_window.winfo_screenheight()
        
        # 创建画布
        self.canvas_capture = tk.Canvas(
            self.capture_window, 
            width=screen_width, 
            height=screen_height,
            cursor="cross"
        )
        self.canvas_capture.pack(fill=tk.BOTH, expand=True)
        
        # 绑定鼠标事件
        self.canvas_capture.bind("<ButtonPress-1>", self.on_press)
        self.canvas_capture.bind("<B1-Motion>", self.on_drag)
        self.canvas_capture.bind("<ButtonRelease-1>", self.on_release)
        
        # 退出按钮
        exit_btn = ttk.Button(
            self.capture_window,
            text="取消截图",
            command=self.cancel_capture
        )
        exit_btn.place(x=10, y=10)
    
    def on_press(self, event):
        """鼠标按下事件"""
        self.start_x = event.x
        self.start_y = event.y
        
        # 如果已有矩形，先删除
        if self.rect:
            self.canvas_capture.delete(self.rect)
        
        # 创建新矩形
        self.rect = self.canvas_capture.create_rectangle(
            self.start_x, self.start_y, 
            self.start_x, self.start_y,
            outline='red', width=2
        )
    
    def on_drag(self, event):
        """鼠标拖动事件"""
        if self.rect:
            # 更新矩形大小
            self.canvas_capture.coords(
                self.rect, 
                self.start_x, self.start_y, 
                event.x, event.y
            )
    
    def on_release(self, event):
        """鼠标释放事件"""
        if not self.start_x or not self.start_y:
            return
            
        # 获取截图区域坐标
        x1, y1 = min(self.start_x, event.x), min(self.start_y, event.y)
        x2, y2 = max(self.start_x, event.x), max(self.start_y, event.y)
        
        # 确保有选择区域
        if x1 == x2 or y1 == y2:
            messagebox.showwarning("警告", "请选择有效的截图区域")
            return
        
        # 截图
        self.capture_window.destroy()
        self.root.deiconify()  # 恢复主窗口
        
        try:
            # 使用pyautogui截图
            screenshot = pyautogui.screenshot(region=(x1, y1, x2-x1, y2-y1))
            
            # 保存截图供识别使用
            self.screenshot = screenshot
            
            # 转换为Tkinter可显示的格式
            img_tk = ImageTk.PhotoImage(screenshot)
            self.screenshot_tk = img_tk  # 保持引用
            
            # 显示图片
            self.image_label.config(image=img_tk)
            
            # 启用识别按钮
            self.recognize_btn.config(state=tk.NORMAL)
            
        except Exception as e:
            messagebox.showerror("错误", f"截图失败: {str(e)}")
    
    def cancel_capture(self):
        """取消截图"""
        if self.capture_window:
            self.capture_window.destroy()
        self.root.deiconify()
    
    def recognize_license(self):
        """识别行驶证"""
        if not self.screenshot:
            messagebox.showwarning("警告", "请先截图")
            return
        
        # 检查网络状态
        if not self.check_internet():
            messagebox.showwarning("警告", "当前处于离线状态，无法进行识别")
            return
            
        try:
            # 将图片转换为base64
            buffered = io.BytesIO()
            self.screenshot.save(buffered, format="PNG")
            img_base64 = base64.b64encode(buffered.getvalue()).decode()
            
            # 获取access token
            access_token = get_access_token()
            
            # 调用API
            url = f"https://aip.baidubce.com/rest/2.0/ocr/v1/vehicle_license?access_token={access_token}"
            payload = {
                'image': img_base64,
                'detect_direction': 'false',
                'unified': 'false',
                'quality_warn': 'false',
                'risk_warn': 'false'
            }
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Accept': 'application/json'
            }
            
            response = requests.post(url, headers=headers, data=payload)
            result = response.json()
            
            # 显示结果
            self.display_result(result)
            
        except Exception as e:
            messagebox.showerror("错误", f"识别失败: {str(e)}")
    
    def display_result(self, result):
        """显示识别结果"""
        # 清除旧结果
        for widget in self.scrollable_frame.winfo_children():
            widget.destroy()
        
        self.result_data = []
        self.result_labels = []
        
        if 'words_result' in result:
            # 提取需要的字段
            words_result = result['words_result']
            
            # 定义需要显示的字段和顺序
            fields_order = [
                ('号牌号码', '号牌号码'),
                ('所有人', '所有人'),
                ('车辆识别代号', '车辆识别代号'),
                ('住址', '住址')
            ]
            
            # 存储结果数据
            for field_key, _ in fields_order:
                if field_key in words_result:
                    self.result_data.append(words_result[field_key]['words'])
            
            # 显示结果
            for text in self.result_data:
                label = tk.Label(
                    self.scrollable_frame,
                    text=text,
                    font=('Arial', 12),
                    padx=10,
                    pady=8,
                    relief=tk.RIDGE,
                    width=40,
                    anchor='w',
                    bg='white'
                )
                label.pack(fill=tk.X, padx=5, pady=2)
                self.result_labels.append(label)
                
                # 绑定事件
                label.bind("<Button-1>", lambda e, t=text, l=label: self.copy_and_highlight(t, l))
                label.bind("<Enter>", lambda e, l=label: l.config(bg="#f0f0f0"))
                label.bind("<Leave>", lambda e, l=label: self.reset_label_color(l))
    
    def copy_and_highlight(self, text, label):
        """复制文本并高亮显示"""
        # 复制到剪贴板
        self.root.clipboard_clear()
        self.root.clipboard_append(text)
        
        # 重置所有标签颜色
        for l in self.result_labels:
            self.reset_label_color(l)
        
        # 高亮当前标签
        label.config(bg="#4CAF50", fg="white")
        
        # 2秒后恢复颜色
        label.after(1000, lambda: self.reset_label_color(label))
    
    def reset_label_color(self, label):
        """恢复标签默认颜色"""
        label.config(bg="white", fg="black")
    
    def clear_all(self):
        """清空所有内容"""
        self.screenshot = None
        self.screenshot_tk = None
        self.image_label.config(image='')
        
        # 清除结果
        for widget in self.scrollable_frame.winfo_children():
            widget.destroy()
        
        self.result_data = []
        self.result_labels = []
        self.recognize_btn.config(state=tk.DISABLED)

def get_access_token():
    """
    使用 AK，SK 生成鉴权签名（Access Token）
    :return: access_token，或是None(如果错误)
    """
    url = "https://aip.baidubce.com/oauth/2.0/token"
    params = {"grant_type": "client_credentials", "client_id": API_KEY, "client_secret": SECRET_KEY}
    return str(requests.post(url, params=params).json().get("access_token"))

if __name__ == '__main__':
    root = tk.Tk()
    app = VehicleLicenseApp(root)
    root.mainloop()